#include "Skill.hh"
#include "Enemy.hh"
#include <iostream>
#include "Player.hh"

namespace DungeonRPG {

// ===== CharacterWithSkills methods =====

void CharacterWithSkills::addSkill(Skill* skill) {
    // Add a new skill to known list
    allSkills.push_back(skill);
    std::cout << "Learned new skill: " << skill->name << "\n";
}

void CharacterWithSkills::equipSkill(int index, int slot) {
    // Equip skill from known list into one of 4 slots
    if (index < 0 || index >= (int)allSkills.size()) return;
    if (slot < 0 || slot >= 4) return;
    if (equippedSkills.size() < 4) equippedSkills.resize(4, nullptr);
    equippedSkills[slot] = allSkills[index];
}

void CharacterWithSkills::showEquippedSkills() const {
    // Print each equipped skill and its cooldown
    std::cout << "Equipped Skills:\n";
    for (int i = 0; i < (int)equippedSkills.size(); ++i) {
        if (equippedSkills[i])
            std::cout << i + 1 << ". " << equippedSkills[i]->name
                      << " - CD: " << equippedSkills[i]->remainingCooldown << "\n";
        else
            std::cout << i + 1 << ". (empty)\n";
    }
}

void CharacterWithSkills::reduceSkillCooldowns() {
    // Reduce cooldowns for all equipped skills
    for (Skill* s : equippedSkills)
        if (s) s->reduceCooldown();
}

Skill* CharacterWithSkills::getSkill(int slot) {
    // Get skill from a specific slot
    if (slot < 0 || slot >= (int)equippedSkills.size()) return nullptr;
    return equippedSkills[slot];
}

CharacterWithSkills::~CharacterWithSkills() {
    // Clean up all learned skills
    for (Skill* s : allSkills) delete s;
}

// ===== Skill activate() implementations =====

void BuffArmor::activate(Character* user, Character*) {
    if (!isReady()) {
        std::cout << "Buff Armor is on cooldown.\n";
        return;
    }
    user->applyTemporaryDefense(5);
    std::cout << user->getName() << "'s defense increased by 5 for this battle.\n";
    resetCooldown();
}

void HealWounds::activate(Character* user, Character* target) {
    // Heals players only, not enemies
    if (!isReady() || !target) return;

    if (Player* ally = dynamic_cast<Player*>(target)) {
        std::cout << user->getName() << " heals " << target->getName() << " for 10 HP.\n";
        ally->heal(10);
    } else {
        std::cout << "You can't heal enemies!\n";
        return;
    }

    resetCooldown();
}

void HeavyStrike::activate(Character* user, Character* target) {
    // Strong physical attack
    if (!isReady() || !target) {
        std::cout << "Heavy Strike unavailable.\n";
        return;
    }
    unsigned dmg = user->getAttack() * 1.5f;
    std::cout << user->getName() << " smashes " << target->getName()
              << " for " << dmg << " heavy damage!\n";
    target->takeDamage(dmg);
    resetCooldown();
}

void Fireball::activate(Character* user, Character* target) {
    // Fire magic with fixed bonus
    if (!isReady() || !target) {
        std::cout << "Fireball failed.\n";
        return;
    }
    unsigned dmg = user->getAttack() + 10;
    std::cout << user->getName() << " casts Fireball on " << target->getName()
              << ", dealing " << dmg << " fire damage!\n";
    target->takeDamage(dmg);
    resetCooldown();
}

void IceSpike::activate(Character* user, Character* target) {
    // Cold spell with slight bonus
    if (!isReady() || !target) {
        std::cout << "Ice Spike failed.\n";
        return;
    }
    unsigned dmg = user->getAttack() + 5;
    std::cout << user->getName() << " casts Ice Spike on " << target->getName()
              << ", dealing " << dmg << " cold damage and slowing them!\n";
    target->takeDamage(dmg);
    resetCooldown();
}

void LightningStrike::activate(Character* user, Character* target) {
    if (!isReady() || !target) {
        std::cout << "Lightning Strike failed.\n";
        return;
    }
    unsigned dmg = user->getAttack() + 8;
    std::cout << user->getName() << " strikes " << target->getName()
              << " with lightning for " << dmg << " damage!\n";
    target->takeDamage(dmg);
    resetCooldown();
}

void PoisonDart::activate(Character* user, Character* target) {
    if (!isReady() || !target) {
        std::cout << "Poison Dart failed.\n";
        return;
    }
    unsigned dmg = user->getAttack();
    std::cout << user->getName() << " hits " << target->getName()
              << " with a poisoned dart! " << dmg << " damage and poisoned!\n";
    target->takeDamage(dmg);
    resetCooldown();
}

void ShieldBash::activate(Character* user, Character* target) {
    if (!isReady() || !target) {
        std::cout << "Shield Bash failed.\n";
        return;
    }
    unsigned dmg = user->getAttack() / 2;
    std::cout << user->getName() << " bashes " << target->getName()
              << " for " << dmg << " damage and stuns them!\n";
    target->takeDamage(dmg);
    if (target->canBeStunned()) {
        static_cast<Enemy*>(target)->setStunned(true);
    }
    resetCooldown();
}

void RallyCry::activate(Character* user, Character*) {
    if (!isReady()) {
        std::cout << "Rally Cry on cooldown.\n";
        return;
    }
    std::cout << user->getName() << " lets out a rallying cry, reducing stress!\n";
    user->relieveStress(10);
    resetCooldown();
}

void BleedStrike::activate(Character* user, Character* target) {
    if (!isReady() || !target) {
        std::cout << "Bleed Strike failed.\n";
        return;
    }
    unsigned dmg = user->getAttack();
    std::cout << user->getName() << " slashes " << target->getName()
              << " for " << dmg << " and causes bleeding!\n";
    target->takeDamage(dmg);
    resetCooldown();
}

void DarkPact::activate(Character* user, Character* target) {
    // High risk, high reward skill
    if (!isReady() || !target) {
        std::cout << "Dark Pact failed.\n";
        return;
    }
    unsigned dmg = user->getAttack() + 20;
    std::cout << user->getName() << " sacrifices their HP for a Dark Pact on "
              << target->getName() << " for " << dmg << " damage!\n";
    target->takeDamage(dmg);
    user->takeDamage(10); // self damage
    resetCooldown();
}

void Purify::activate(Character* user, Character*) {
    if (!isReady()) {
        std::cout << "Purify on cooldown.\n";
        return;
    }
    std::cout << user->getName() << " casts Purify, cleansing negative effects.\n";
    user->relieveStress(5);
    resetCooldown();
}

void RapidShot::activate(Character* user, Character* target) {
    if (!isReady() || !target) {
        std::cout << "Rapid Shot failed.\n";
        return;
    }
    unsigned dmg = user->getAttack() / 2;
    std::cout << user->getName() << " rapidly fires two shots at "
              << target->getName() << " for " << dmg * 2 << " total damage!\n";
    target->takeDamage(dmg);
    target->takeDamage(dmg);
    resetCooldown();
}

void MarkTarget::activate(Character* user, Character* target) {
    if (!isReady() || !target) {
        std::cout << "Mark Target failed.\n";
        return;
    }
    std::cout << user->getName() << " marks " << target->getName()
              << ", making them more vulnerable!\n";
    target->setMarked(true);
    resetCooldown();
}

void Fortify::activate(Character* user, Character*) {
    if (!isReady()) {
        std::cout << "Fortify is not ready.\n";
        return;
    }
    user->applyTemporaryDefense(8);
    std::cout << user->getName() << " fortifies their defenses for this battle!\n";
    resetCooldown();
}

// ===== Skill constructors =====

HealWounds::HealWounds()        : Skill("Heal Wounds", "Heals the target for 10 HP.", 3) {}
HeavyStrike::HeavyStrike()      : Skill("Heavy Strike", "Deals heavy damage to the target.", 5) {}
BuffArmor::BuffArmor()          : Skill("Buff Armor", "Temporarily increases defense by 5.", 3) {}
Fireball::Fireball()            : Skill("Fireball", "Deals 10 + ATK fire damage.", 4) {}
IceSpike::IceSpike()            : Skill("Ice Spike", "Deals 5 + ATK cold damage.", 3) {}
LightningStrike::LightningStrike() : Skill("Lightning", "Deals 8 + ATK electric damage.", 3) {}
PoisonDart::PoisonDart()        : Skill("Poison Dart", "Deals damage and poisons.", 2) {}
ShieldBash::ShieldBash()        : Skill("Shield Bash", "Deals light damage and stuns.", 3) {}
RallyCry::RallyCry()            : Skill("Rally Cry", "Reduces stress for allies.", 2) {}
BleedStrike::BleedStrike()      : Skill("Bleed Strike", "Deals damage and applies bleed.", 3) {}
DarkPact::DarkPact()            : Skill("Dark Pact", "High damage with HP cost.", 5) {}
Purify::Purify()                : Skill("Purify", "Removes debuffs and reduces stress.", 3) {}
RapidShot::RapidShot()          : Skill("Rapid Shot", "Deals two quick hits.", 2) {}
MarkTarget::MarkTarget()        : Skill("Mark Target", "Increases target vulnerability.", 3) {}
Fortify::Fortify()              : Skill("Fortify", "Reduces incoming damage.", 4) {}

}
